package controllers;

import play.*;
import play.cache.Cache;
import play.data.validation.Required;
import play.db.jpa.Blob;
import play.db.jpa.JPABase;
import play.libs.MimeTypes;
import play.mvc.*;
import utils.Calculator;
import utils.Classement;

import groovy.json.JsonOutput;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.*;

import org.hibernate.connection.UserSuppliedConnectionProvider;
import org.hibernate.mapping.Array;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonWriter;

import models.*;

public class Application extends Controller {

	static List<Formation> listFormationToUpdate = null;
	
	@Before
	public static void onStart(){				
		listFormationToUpdate = Formation.find(
				"order by libelleFormation").fetch();
	}
	
	public static void index() {
		List<Formation> listFormation = Formation.find(
				"order by libelleFormation").fetch();
		render(listFormation);
	}

	/**
	 * Méthode permettant d'afficher la page des statistiques
	 */
	public static void statistiques() {
		Collection<Intervention> listIntervention = null;
		List<Intervention> finalListIntervention = new ArrayList<Intervention>();
		
		if (session.get("user_statut").equalsIgnoreCase("Student")) {
			Student connectedStudent = (Student) Cache.get("user");
			listIntervention = Intervention.find(
					"byFormationIntervention",
					connectedStudent.formationStudent).fetch();
			for(Intervention i : listIntervention){
				i.setMoyenneIntervention(Classement.getMoyenneGeneraleForIntervention(i));
				finalListIntervention.add(i);
			}

		} else if (session.get("user_statut").equalsIgnoreCase("Enseignant")) {
			Enseignant connectedTeacher = (Enseignant) Cache.get("user");
			connectedTeacher = Enseignant.findById(connectedTeacher.id);
//			List<Intervention> listInterventionEnseignant = Intervention.find("byEnseignantIntervention", connectedTeacher).fetch(10);
			for(Intervention i : connectedTeacher.listInterventionEnseignant){
				i.setMoyenneIntervention(Classement.getMoyenneGeneraleForIntervention(i));
				finalListIntervention.add(i);
			}
		}


		render(finalListIntervention,listFormationToUpdate);
	}

	/**
	 * Méthode permettant de créer un utilisateur en base de données
	 * @param userToCreate : utilisateur à créer
	 * @param user_formation : formation de l'utilisateur dans le cas d'un étudiant
	 * @param user_avatar : avatar de l'utilisateur
	 */
	public static void createUser(@Required User userToCreate, @Required String user_categorie, String user_formation) {
		if (validation.hasErrors()) {
			flash.error("Veuillez vérifier que tous les champs obligatoires sont complétés","");
			index();
		}
		
		boolean success = false;
		
		if (user_categorie.equalsIgnoreCase("student")) {
			Formation userFormation = Formation.find("byId", Long.parseLong(user_formation)).first();
			Student studentToCreate = new Student(userToCreate, userFormation, new HashSet<Evaluation2>());
			if(studentToCreate.create())
				success = true;
		} else {
			Enseignant enseignantToCreate = new Enseignant(userToCreate, new HashSet<Intervention>());
			File avatar = null;

			try {
				if (!userToCreate.avatarPathUser.exists())
					avatar = new File(Play.applicationPath,"/public/images/avatar_teacher.jpg");

				enseignantToCreate.avatarPathUser.set(new FileInputStream(avatar),
						MimeTypes.getContentType(avatar.getName()));

			} catch (FileNotFoundException ex) {
				ex.printStackTrace();
			}
			
			if(enseignantToCreate.create())
				success = true;
		}
		
		if(success){
			System.out.println(userToCreate.emailUser);
			flash.success("Compte créé avec succès !");
			index();
		}else{
			flash.error("Une erreur s'est produite lors de la création du compte");
			index();
		}
	}

	/**
	 * Méthode permettant l'authentification de l'utilisateur
	 * @param user_email
	 * @param user_password
	 */
	public static void connectUser(@Required String user_email, @Required String user_password) {
		if (validation.hasErrors()) {
			flash.error(
					"Veuillez vérifier que tous les champs obligatoires sont complétés",
					"");
			index();
		}

		User u = User.connect(user_email, user_password);

		if (u == null) {
			flash.error("Mauvais identifiants");
			index();
		} else {
			
			session.put("user_statut", u.getDtype());
			session.put("user_id", u.id);
			session.put("user_lastname", u.lastNameUser);
			
			if (u.getDtype().equalsIgnoreCase("Student")) {
				Student connectedUser = Student.findById(u.id);
				Cache.add("user", connectedUser,"1h");
			} else if (u.getDtype().equalsIgnoreCase("Enseignant")) {
				Enseignant connectedUser = Enseignant.findById(u.id);
				Cache.add("user", connectedUser,"1h");
			}
		}
		
		
		usr_display_profile(u.id,u.lastNameUser);
	}

	/**
	 * Méthode permettant d'afficher les informations d'un utilisateur
	 */
	public static void usr_display_profile(Long id, String lastname) {
		renderArgs.put("listFormationToUpdate", listFormationToUpdate);
		
		User userToFind = User.findById(id);
		
		if( userToFind.getDtype().equalsIgnoreCase("Student") ){
			Student userToDisplay = Student.findById(id);
			List<Intervention> interventionsOfStudent = Intervention.find("byFormationIntervention", userToDisplay.formationStudent).fetch();
			render(userToDisplay,interventionsOfStudent);
		}else{
			Enseignant userToDisplay = Enseignant.findById(id);
			render(userToDisplay);
		}
	}
	
	public static void uploadImage(File pic){
		User userToModify = User.findById(Long.parseLong(session.get("user_id")));

		if(pic.isFile()){
				try {
					userToModify.avatarPathUser.getFile().delete();
					userToModify.avatarPathUser = new Blob();
					userToModify.avatarPathUser.set(new FileInputStream(pic),
							MimeTypes.getContentType(pic.getName()));
					
					userToModify.save();
					userToModify.refresh();

				} catch (FileNotFoundException e) {
					e.printStackTrace();
				}
		}
		
		if(session.get("user_statut").equalsIgnoreCase("student")){
			Student userConnected = (Student)Cache.get("user");
			userConnected.avatarPathUser = userToModify.avatarPathUser;
			Cache.replace("user", userConnected);
		}else{
			Enseignant userConnected = (Enseignant)Cache.get("user");
			userConnected.avatarPathUser = userToModify.avatarPathUser;
			Cache.replace("user", userConnected);						
		}
		
		renderXml("<statut>ok</statut>");
	}
	
	public static void search(String searchword){		
		List<User> userToSearch = User.find("lastNameUser like ? OR firstNameUser like ?", "%"+searchword+"%", "%"+searchword+"%").fetch();
		JsonArray root = new JsonArray();
		for(User userFind : userToSearch){
			JsonObject rowJson = new JsonObject();
			rowJson.addProperty("id", userFind.id);
			rowJson.addProperty("lastname", userFind.lastNameUser);
			rowJson.addProperty("firstname", userFind.firstNameUser);
			rowJson.addProperty("type", userFind.getDtype());
			root.add(rowJson);
		}
		
		renderJSON(root);
	}
	
	/**
	 * Méthode permettant de mettre un jour un utilisateur dans la base de données
	 * @param updateUser : nouvelles informations de l'utilisateur
	 * @param Formation : nouvelles formations dans le cas d'un étudiant
	 */
	public static void update(User updateUser, Formation formationToUpdate){
		
		if(session.get("user_statut").equalsIgnoreCase("Student")){
			Student oldUser = Student.findById(session.get("user_id"));
			updateUser.matchWithOtherUser(oldUser);
			updateUser.save();
			if (formationToUpdate != null) {
				oldUser.formationStudent = formationToUpdate;
				oldUser.save();
			}
			Student connectedUser = new Student(updateUser, oldUser.formationStudent, oldUser.listEvaluation2Student);
			Cache.replace("user", connectedUser);
			flash.success("Informations mises à jours avec succés", "");
			usr_display_profile(connectedUser.id,connectedUser.lastNameUser);
		}else if(session.get("user_statut").equalsIgnoreCase("Enseignant")){
			Enseignant oldUser = (Enseignant)Cache.get("user");
			updateUser.matchWithOtherUser(oldUser);
			updateUser.save();
			Enseignant connectedUser = new Enseignant(updateUser, oldUser.listInterventionEnseignant);
			Cache.replace("user", connectedUser);
			flash.success("Informations mises à jours avec succés", "");
			usr_display_profile(connectedUser.id,connectedUser.lastNameUser);
		}		
	}

	/**
	 * Méthode permettant la déconnexion de l'utilisateur
	 */
	public static void deconnectUser() {
		session.clear();
		Cache.clear();
		index();
	}

}